class Outer {
    public void SynchronizedDemo1() {
        synchronized (this) {

        }
    }

    //直接修饰普通方法
    public synchronized void SynchronizedDemo2() {
    }
    public void SynchronizedDemo3() {
        synchronized(this) {

        }
    }
    //修饰静态方法
    public synchronized static void SynchronizedDemo4() {
    }
    public void SynchronizedDemo5() {
        synchronized(Outer.class) {
        }
    }
}
public class Test {
    /**
     * 线程安全问题
     *      1.观察线程不安全
     *      2.线程安全的概念
     *      3.线程不安全的原因
     *      4.如何解决线程不安全问题
     *      5.synchronized关键字
     */
    /**
     * synchronized
     *      1.synchronized特征
     *      2.synchronized使用示例
     */
    public static void main(String[] args) {
        /**
         * synchronized使用示例
         *      1.修饰代码块->明确指定锁定哪个对象
         *          1.锁任意对象
         *          2.锁当前对象
         *      2.普通方法
         *      3.静态方法
         */
        Object locker = new Object();
        //1.锁任意对象
        Thread t1 = new Thread(()->{
            synchronized(locker) {
                for(int i = 0;i < 5000;i++) {
                    count++;
                }
            }
        });

        //2.锁当前对象
        Thread t2 = new Thread(()->{
            synchronized(locker) {
                for(int i = 0;i < 5000;i++) {
                    count++;
                }
            }
        });
    }
    static int count = 0;

    public static void main5(String[] args) throws InterruptedException {
        /**
         * synchronized特征
         *      1.互斥->加锁
         *      2.可重入->synchronized对同一线程可多次加锁,不会出现死锁问题
         */
        Object locker = new Object();


         Thread t1 = new Thread(()->{
             synchronized(locker) {
                 for(int i = 0;i <= 50000;i++) {
                     count++;
                 }
             }
         });

         Thread t2 = new Thread(()->{
             synchronized(locker) {
                 for(int i = 0;i <= 50000;i++) {
                     count++;
                 }
             }
         });

         t1.start();
         t2.start();
         t1.join();
         t2.join();

        System.out.println("count: " + count);
    }
    /**
     * 如何解决线程不安全问题
     *      1.加锁
     */
    public static void main4(String[] args) {
        /**
         * 关于锁
         *      1.锁的核心操作->加锁 解锁
         *      2.锁的主要特性:互斥
         *      3.代码中,可以创建多个锁,如果针对的是不同线程,则不会出现互斥问题
         */
    }
    public static void main3(String[] args) {
        /**
         * 线程不安全的原因
         *      1.线程在系统中是随机调度,抢占式执行的->根本原因
         *      2.多个线程同时修改一个变量
         *      3.线程针对变量的修改操作不是原子的
         *      4.内存可见性问题
         *      5.指令重排序问题
         */
    }
    public static void main2(String[] args) {
        /**
         * 线程安全的概念
         *      在多线程环境下代码运行结果符合预期,即符合在单线程环境下的结果,则证明线程是安全的
         */
    }

    public static void main1(String[] args) {
        /**
         * 观察线程不安全
         *      1.count++的简单方法,其实需要(load,add,save)三个执行指令,具体执行顺序是随机变化的,会进行覆盖.
         *      2.产生了多个线程,线程执行顺序是随机性的,不可确定的
         */
    }
}
